﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using JtextEpicsInterface;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using System.Collections;
using System.Runtime.Serialization.Formatters.Binary;

namespace JEPlugIn_heartBeats
{
    /// <summary>
    /// this plugin make the value go up and down at a preset rate ,heart beat rate is set by scan interval of this value
    /// </summary>
    public class PlugInHeartBeats : IJEPlugIn
    {
        const string MyName = "SaveLoader";
        string fileName;
        bool isFirstTime;
        bool isXmlSerialize;
        public string PlugInName
        {
            get
            {
                return MyName;
            }
        }

        /// <summary>
        /// Initialize the plug in.
        /// <para>This is call onec at the beginning for the server start up,and the record is not going to initialize any thing later so finish all the initialize job.
        /// <para>the heartVal is give to the Record who called this and the heartVal increasce by the heartRate,till it reached the lo,hi limit and then it go reverse</para>
        /// </summary>
        /// <param name="iniObject">hi lo rate,ini_value.</param>
        public void IniPlugIn(object iniObject,IJERecord record)    //usually a string
        {
            //init you plugin here
            string strConfig = (string)iniObject;
            string[] strConfigs = Regex.Split(strConfig, ";", RegexOptions.IgnoreCase);
            int configIndex = strConfig.IndexOf("SaveLoader") + 1;
            fileName = AppDomain.CurrentDomain.BaseDirectory.ToString() + "SaveLoader\\" + strConfigs[configIndex];
            isXmlSerialize = Convert.ToBoolean(strConfigs[configIndex + 1]);
            isFirstTime = true;
            Console.WriteLine("SaveLoader Init");
        }

        /// <summary>
        /// Runs the plug in.
        /// <Para>the record will call this each time it get flushed,for input and out put there  maybe differences.Look up example if you are making plugin</Para>
        /// </summary>
        /// <param name="myRecord">My record.The record that called the plugIn,you can set get and do anything</param>
        /// <returns>if successful</returns>
        public bool RunPlugIn(IJERecord myRecord)
        {

            //do somthing

            if (isFirstTime == true)
            {
                object val = loadIniValue(myRecord.VAL);
                //output the value
                if (val != null)
                {
                    myRecord.VAL = val;
                }
                isFirstTime = false;
            }
            else
            {
                saveValue(myRecord.VAL);
            }

            return true;

        }




        /// <summary>
        /// Kills the plug in when you don't need it.
        /// </summary>
        public void KillPlugIn()
        { //kill your plugin
        }

        private void saveValue(object val)
        {
            if (isXmlSerialize == true)
            {
                if (val is Array)
                {
                    Array tArray = (Array)val;
                    ArrayList tArrayList = ArrayList.Adapter(tArray);
                    XmlSerializer xs = new XmlSerializer(typeof(ArrayList));
                    Stream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
                    xs.Serialize(fs, tArrayList);
                    //Console.WriteLine("Value Saved: "+ val.ToString());
                    fs.Close();
                }
                else
                {
                    XmlSerializer xs = new XmlSerializer(typeof(object));
                    Stream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
                    xs.Serialize(fs, val);
                    //Console.WriteLine("Value Saved: "+ val.ToString());
                    fs.Close();
                }
            }
            else
            {
                //do binary serialize
                Stream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(fs, val);
                fs.Close();
            }
        }

        private object loadIniValue(object val)
        {
            try
            {
                if (isXmlSerialize == true)
                {
                    if (val is Array)
                    {
                        XmlSerializer xs = new XmlSerializer(typeof(ArrayList));
                        Stream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                        Console.WriteLine("deserialize: "+ fileName);
                        ArrayList rVal = (ArrayList)xs.Deserialize(fs);
                        Console.WriteLine("clos: " + fileName);
                        fs.Close();
                        Console.WriteLine("closed: " + fileName);
                        Array tArray = rVal.ToArray(typeof(double[]));
                        Console.WriteLine("Value Loaded: " + tArray.ToString());
                        return (tArray);
                    }
                    else
                    {
                        XmlSerializer xs = new XmlSerializer(typeof(object));
                        Stream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                        object rVal = (object)xs.Deserialize(fs);
                        fs.Close();
                        Console.WriteLine("Value Loaded: " + rVal.ToString());
                        return rVal;
                    }
                }
                else
                {
                    //do binary
                    Stream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                    BinaryFormatter formatter = new BinaryFormatter();
                    object rVal = formatter.Deserialize(fs);
                    fs.Close();
                    Console.WriteLine("Value Loaded: " + rVal.ToString());
                    return rVal;
                }
            }
            catch
            {
                return null;
            }
        }

    }
}